#!/bin/sh
set -e

# Set WORKDIR default if not set
WORKDIR=${WORKDIR:-/app}

# Set APP_NAME default if not set
APP_NAME=${APP_NAME:-spring-boot}

# Ensure log, config, and tmp directories exist
# ==================== Prepare directories ====================
mkdir -p ${WORKDIR}/logs ${WORKDIR}/config ${WORKDIR}/tmp

# Note: unzip should be installed in Dockerfile build stage for performance.
# If unzip is not present, the extraction step will fail with a clear error.

# JVM parameter references:
# JVM parameter upgrade tool: https://jacoline.dev/inspect
# JVM parameter dictionary: https://chriswhocodes.com

# When using nacos, you can add the following parameters to JVM_DEFAULT_OPTS or JVM_OPTS
# -Djava.io.tmpdir=${WORKDIR}/tmp \
# -DJM.LOG.PATH=${WORKDIR}/logs/nacos \
# -DJM.SNAPSHOT.PATH=${WORKDIR}/tmp \
# -Dcom.alibaba.nacos.naming.cache.dir=${WORKDIR}/tmp \

# ==================== Assemble JVM options ====================
# Default JVM options
JVM_DEFAULT_OPTS="\
-Djava.io.tmpdir=${WORKDIR}/tmp \
-DJM.LOG.PATH=${WORKDIR}/logs/nacos \
-DJM.SNAPSHOT.PATH=${WORKDIR}/tmp \
-Dcom.alibaba.nacos.naming.cache.dir=${WORKDIR}/tmp \
-XX:SharedArchiveFile=${WORKDIR}/app.jsa \
-XX:+TieredCompilation \
-XX:+SegmentedCodeCache \
-XX:+UseStringDeduplication \
-XX:-OmitStackTraceInFastThrow \
-XX:+AlwaysPreTouch \
-XX:+DisableExplicitGC \
-XX:+UseCompressedOops \
-XX:+UseCompactObjectHeaders \
-Djava.awt.headless=true \
-Dfile.encoding=UTF-8 \
-Dspring.profiles.active=${PROFILE} \
-Dserver.port=${PORT}"

# Initialize opts variable
opts="${JVM_DEFAULT_OPTS}"

if [ "${ENABLE_ERROR_LOGS}" = 'true' ]
then
    opts="\
${opts} \
-XX:ErrorFile=${WORKDIR}/logs/hs_err_pid.log \
-XX:HeapDumpPath=${WORKDIR}/logs/java_heapdump.hprof \
-XX:+ExtensiveErrorReports \
-XX:+HeapDumpOnOutOfMemoryError"
fi

if [ "${ENABLE_GC_LOGS}" = 'true' ]
then
    opts="\
${opts} \
-Xlog:async \
-Xlog:gc*=info:file=${WORKDIR}/logs/gc_%t.log:utctime,level,tags:filecount=10,filesize=10M \
-Xlog:jit+compilation=info:file=${WORKDIR}/logs/jit_compile_%t.log:utctime,level,tags:filecount=10,filesize=10M \
-Xlog:safepoint=info:file=${WORKDIR}/logs/safepoint_%t.log:utctime,level,tags:filecount=10,filesize=10M"
fi

if [ "${ENABLE_JVM_LOGS}" = 'true' ]
then
    opts="\
${opts} \
-XX:+UnlockDiagnosticVMOptions \
-XX:LogFile=${WORKDIR}/logs/hotspot.log \
-XX:+LogCompilation \
-XX:+PrintCompilation \
-XX:+PrintInlining"
fi

# Append JVM_APPEND_OPTS if present
if [ -n "${JVM_APPEND_OPTS}" ]
then
    opts="${opts} ${JVM_APPEND_OPTS}"
fi

# Override with JVM_OPTS if present
if [ -n "${JVM_OPTS}" ]
then
    opts="${JVM_OPTS}"
fi

# ==================== Extract configuration files ====================
# Extract config files (*.yml, *.yaml, *.properties) from app.jar to config dir
unzip_and_log() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S.000')
    local log_file="${WORKDIR}/logs/stdout.log"
    local config_file="${WORKDIR}/logs/stdout.log"
    local log_str="$(unzip ${unzip_opts} ${WORKDIR}/app.jar *.yml *.yaml *.properties -d ${WORKDIR}/config 2>&1 | grep inflating | tr '\n' ', '|sed -E 's/inflating:? *//g')"
    echo "${timestamp} ${APP_NAME} $$ [null] INFO  console [null] - Inflating config files: ${log_str} to ${WORKDIR}/config"
    echo "${timestamp} ${APP_NAME} INFO console [null] - Inflating config files: ${log_str} to ${WORKDIR}/config" >> "${log_file}"
}


unzip_opts="-n"
if [ "${OVERWRITE_CONFIG}" = 'true' ]
then
    unzip_opts="${unzip_opts} -o"
    unzip_and_log
fi

# ==================== Log JVM options ====================
# Function to log JVM options in specified format
log_jvm_opts() {
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S.000')
    local log_file="${WORKDIR}/logs/stdout.log"
    local formatted_opts=$(echo "${opts}" | tr ' ' '\n' | grep -v '^$' | tr '\n' ' ' | sed 's/[[:space:]]*$//')
    echo "${timestamp} ${APP_NAME} $$ [null] INFO  console [null] - JVM Options: ${formatted_opts}"
    echo "${timestamp} ${APP_NAME} INFO console [null] - JVM Options: ${formatted_opts}" >> "${log_file}"
}
# Log JVM options to file
log_jvm_opts
# ==================== Start application ====================
exec java ${opts} -jar ${WORKDIR}/app.jar
